import sys
import serial.tools.list_ports
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtWidgets import (QApplication, QWidget, QPushButton, QVBoxLayout, QHBoxLayout,
                             QMenuBar, QAction, QStyleFactory, QLabel, QTextEdit, QSplitter,
                             QSizePolicy, QCheckBox, QComboBox, QGroupBox, QMenu, QMessageBox)
from PyQt5.QtGui import QFont

import time
import serial

from custom_ui.lineEdit import NewLineEdit
from ext.UQTextEdit import UQTextEdit


class Qserial_Assistant(QWidget):
    def __init__(self):
        super().__init__()
        # 初始化一个计时器用于定时自动发送数据
        # self.ser = 1
        # self.com_port
        self.auto_send_timer = QTimer()
        self.auto_send_timer.timeout.connect(self.send_data)  # 定时器触发发送数据函数
        self.auto_send_interval = 1000  # 自动发送的时间间隔，默认 1000 毫秒
        self.init_UI()

    def init_UI(self):
        self.setWindowTitle('串口调试助手v1.0')
        self.setFixedSize(960, 730)

        self.Font = QFont()
        self.Font.setFamily('楷体')
        self.Font.setPointSize(14)

        # 创建菜单栏
        menu_bar = QMenuBar(self)
        menu_bar.setFont(self.Font)

        self.home_action = QAction('主页', self)
        self.help_action = QMenu('帮助', self)
        self.about_action = QAction('关于', self)

        self.chinese_mode_action = QAction("中文模式", self)
        self.english_mode_action = QAction("英文模式", self)
        self.upgrade_action = QAction("版本升级", self)

        self.help_action.addActions([self.chinese_mode_action, self.english_mode_action, self.upgrade_action])

        menu_bar.addAction(self.home_action)
        menu_bar.addMenu(self.help_action)
        menu_bar.addAction(self.about_action)

        self.home_action.setCheckable(True)
        # self.help_action.setCheckable(True)
        self.about_action.setCheckable(True)

        self.home_action.triggered.connect(self.show_home)
        # self.help_action.triggered.connect(self.show_help)
        self.about_action.triggered.connect(self.show_about)
        self.chinese_mode_action.triggered.connect(self.set_chinese_mode)
        self.english_mode_action.triggered.connect(self.set_english_mode)
        self.upgrade_action.triggered.connect(self.Version_box)

        # 创建主布局
        self.main_layout = QVBoxLayout()
        self.main_layout.setMenuBar(menu_bar)

        # 创建堆叠小部件来管理不同页面
        self.content_widget = QWidget()
        self.content_layout = QVBoxLayout(self.content_widget)

        # 创建主页内容
        self.home_widget = QWidget()
        self.home_layout = QHBoxLayout(self.home_widget)  # 使用水平布局

        # 创建左侧垂直布局用于放置缓冲区
        right_layout = QVBoxLayout()
        left_layout = QVBoxLayout()

        # 创建发送和接收缓冲区
        self.receive_buffer = QTextEdit()
        self.receive_buffer.setFont(self.Font)
        self.receive_buffer.setPlaceholderText("接收缓冲区")
        self.receive_buffer.setFixedWidth(600)  # 设置固定宽度
        self.receive_buffer.setMinimumHeight(300)  # 设置最小高度
        self.receive_buffer.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)  # 始终显示垂直滚动条

        self.send_buffer = UQTextEdit()
        self.send_buffer.setFont(self.Font)
        self.send_buffer.setPlaceholderText("发送缓冲区")
        self.send_buffer.setFixedWidth(600)  # 设置固定宽度
        self.send_buffer.setMinimumHeight(150)  # 设置最小高度
        self.send_buffer.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)  # 始终显示垂直滚动条
        self.send_buffer.backgroundColor("#FFD700")

        # 创建复选框
        self.auto_send_checkbox = QCheckBox("自动发送")
        self.auto_send_checkbox.setFont(self.Font)
        self.auto_send_checkbox.stateChanged.connect(self.toggle_auto_send)  # 添加状态变化的

        self.send_button = QPushButton()
        self.send_button.setText("发送数据")
        self.send_button.setFont(self.Font)
        self.send_button.setFixedWidth(100)
        self.send_button.setStyleSheet("background-color: red; color: white;")  # 默认红色
        self.send_button.clicked.connect(self.send_data)

        self.clear_send_buffer_button = QPushButton()
        self.clear_send_buffer_button.setText("清空发送缓冲区")
        self.clear_send_buffer_button.setFont(self.Font)
        self.clear_send_buffer_button.setFixedWidth(170)
        self.clear_send_buffer_button.setStyleSheet("background-color: red; color: white;")  # 默认红色
        self.clear_send_buffer_button.clicked.connect(self.clear_SendBuffer)

        self.clear_receive_buffer_button = QPushButton()
        self.clear_receive_buffer_button.setText("清空接收缓冲区")
        self.clear_receive_buffer_button.setFont(self.Font)
        self.clear_receive_buffer_button.setFixedWidth(170)
        self.clear_receive_buffer_button.setStyleSheet("background-color: red; color: white;")  # 默认红色
        self.clear_receive_buffer_button.clicked.connect(self.clear_ReceiveBuffer)

        # 创建水平布局，将复选框和三个按钮放在同一行
        button_layout = QHBoxLayout()
        button_layout.addWidget(self.auto_send_checkbox)
        button_layout.addWidget(self.send_button)
        button_layout.addWidget(self.clear_send_buffer_button)
        button_layout.addWidget(self.clear_receive_buffer_button)

        # 将缓冲区添加到左侧布局
        right_layout.addWidget(self.receive_buffer)
        right_layout.addWidget(self.send_buffer)
        right_layout.addLayout(button_layout)  # 添加按钮布局
        right_layout.addStretch(1)  # 添加弹性空间，使控件靠上

        # 创建串口设置
        # self.serial_label = QLabel("串口设置\n")
        # self.serial_label.setFont(font)

        # 创建一个QGroupBox来包围外围设置
        self.serial_settings_groupbox = QGroupBox("  串口设置")
        self.serial_settings_groupbox.setFont(self.Font)

        # 创建一个QGroupBox来包围外围设置
        self.Switch_settings_groupbox = QGroupBox("  串口开关")
        self.Switch_settings_groupbox.setFont(self.Font)

        # 创建一个垂直布局用于GroupBox内的控件布局
        self.serial_settings_layout = QVBoxLayout()
        self.Switcher_settings_layout = QVBoxLayout()

        self.Com_Number = QLabel("端口号")
        self.Com_Number.setFont(self.Font)

        self.Baud_label = QLabel("波特率")
        self.Baud_label.setFont(self.Font)

        self.DataBit_label = QLabel("数据位")
        self.DataBit_label.setFont(self.Font)

        self.StopBit_Label = QLabel("停止位")
        self.StopBit_Label.setFont(self.Font)

        self.VerifyBit_Label = QLabel("奇偶校验位")
        self.VerifyBit_Label.setFont(self.Font)

        self.HardControl_Label = QLabel("硬件流控制")
        self.HardControl_Label.setFont(self.Font)

        self.Enter_Label = QLabel("\n")
        self.Enter_Label.setFont(self.Font)

        self.Or_Label = QLabel("   or")
        self.Or_Label.setFont(self.Font)

        # self.Switcher_Label =QLabel("  串口开关")
        # self.Switcher_Label.setFont(font)

        # 创建COM端口选择下拉菜单
        self.com_selector = QComboBox()
        self.com_selector.setFont(self.Font)
        self.com_selector.setFixedWidth(100)
        self.update_com_ports()  # 更新可用的COM端口

        # 创建波特率选择下拉菜单
        self.baudrate_selector = QComboBox()
        self.baudrate_selector.setFont(self.Font)
        self.baudrate_selector.setFixedWidth(100)
        self.baudrate_selector.addItems(
            ["600", "1200", "4800", "9600", "14400", "19200", "28800", "38400", "57600", "115200"])
        self.baudrate_selector.setCurrentText("9600")  # 默认选中9600

        # 创建数据位选择下拉菜单
        self.DataBit_selector = QComboBox()
        self.DataBit_selector.setFont(self.Font)
        self.DataBit_selector.setFixedWidth(100)
        self.DataBit_selector.addItems(["7", "8"])
        self.DataBit_selector.setCurrentText("8")  # 默认选中9600

        # 创建停止位选择下拉菜单
        self.StopBit_selector = QComboBox()
        self.StopBit_selector.setFont(self.Font)
        self.StopBit_selector.setFixedWidth(100)
        self.StopBit_selector.addItems(["1", "1.5", "2"])
        self.StopBit_selector.setCurrentText("1")  # 默认 1位

        # 创建奇偶校验位
        self.VerifyBit_selector = QComboBox()
        self.VerifyBit_selector.setFont(self.Font)
        self.VerifyBit_selector.setFixedWidth(100)
        self.VerifyBit_selector.addItems(["无校验", "奇校验", "偶校验", "0校验", "1校验"])
        self.VerifyBit_selector.setCurrentText("无校验")  # 默认 无

        # 创建硬件流控制
        self.HardControl_selector = QComboBox()
        self.HardControl_selector.setFont(self.Font)
        self.HardControl_selector.setFixedWidth(100)
        self.HardControl_selector.addItems(["无", "有"])
        self.HardControl_selector.setCurrentText("无")  # 默认 无

        # 创建串口操作按钮
        self.open_button = QPushButton()
        self.open_button.setText("打开")
        self.open_button.setFont(self.Font)
        self.open_button.setFixedWidth(100)
        self.open_button.setStyleSheet("background-color: red; color: white;")  # 默认红色
        self.open_button.clicked.connect(self.open_serial)

        self.close_button = QPushButton()
        self.close_button.setText("关闭")
        self.close_button.setFont(self.Font)
        self.close_button.setFixedWidth(100)
        self.close_button.setStyleSheet("background-color: green; color: white;")  # 默认绿色
        self.close_button.clicked.connect(self.close_serial)

        # 将串口设置添加到右侧布局
        # left_layout.addWidget(self.serial_label)
        self.serial_settings_layout.addWidget(self.Com_Number)
        self.serial_settings_layout.addWidget(self.com_selector)
        self.serial_settings_layout.addWidget(self.Baud_label)
        self.serial_settings_layout.addWidget(self.baudrate_selector)
        self.serial_settings_layout.addWidget(self.DataBit_label)
        self.serial_settings_layout.addWidget(self.DataBit_selector)
        self.serial_settings_layout.addWidget(self.StopBit_Label)
        self.serial_settings_layout.addWidget(self.StopBit_selector)
        self.serial_settings_layout.addWidget(self.VerifyBit_Label)
        self.serial_settings_layout.addWidget(self.VerifyBit_selector)
        self.serial_settings_layout.addWidget(self.HardControl_Label)
        self.serial_settings_layout.addWidget(self.HardControl_selector)

        # 将串口开关添加到右侧布局
        self.Switcher_settings_layout.addWidget(self.open_button)
        self.Switcher_settings_layout.addWidget(self.Or_Label)
        self.Switcher_settings_layout.addWidget(self.close_button)

        # 将serial_settings_layout应用到serial_settings_groupbox
        self.serial_settings_groupbox.setLayout(self.serial_settings_layout)
        self.Switch_settings_groupbox.setLayout(self.Switcher_settings_layout)

        # 将串口设置的GroupBox添加到右侧布局
        left_layout.addWidget(self.serial_settings_groupbox)
        # left_layout.addWidget(self.Enter_Label)
        # left_layout.addWidget(self.Switcher_Label)
        # left_layout.addWidget(self.open_button)
        # left_layout.addWidget(self.Enter_Label)
        # left_layout.addWidget(self.close_button)
        left_layout.addWidget(self.Switch_settings_groupbox)
        left_layout.addStretch(1)  # 添加弹性空间，使控件靠上

        # 将右侧布局添加到主页布局
        self.home_layout.addLayout(left_layout)
        # self.home_layout.addStretch(1)  # 添加弹性空间，使控件靠左

        # 将左侧布局添加到主页布局
        self.home_layout.addLayout(right_layout)
        # self.home_layout.addStretch(1)  # 添加弹性空间，使控件靠左
        self.right_list_layout = QVBoxLayout()

        self.right_list_layout.addLayout(self.create_command_row("asdfasdf"))
        self.right_list_layout.addStretch(1)
        self.home_layout.addLayout(self.right_list_layout)
        # 创建帮助和关于页面的标签
        self.help_label = QLabel('这是帮助内容')
        self.help_label.setFont(self.Font)

        self.about_info = QLabel('工具信息\n')
        self.about_info.setFont(self.Font)
        self.about_Version = QLabel('Versions: v1.0')
        self.about_Version.setFont(self.Font)
        self.about_author = QLabel('  Author: <Kunlunzr>')
        self.about_author.setFont(self.Font)
        self.about_Mail = QLabel("  \t E-mail: 2876154521@qq.com")
        self.about_Mail.setFont(self.Font)

        self.about_Version.setAlignment(Qt.AlignCenter)  # 将内容居中 对齐
        self.about_author.setAlignment(Qt.AlignCenter)  # 将内容居中 对齐
        self.about_Mail.setAlignment(Qt.AlignCenter)  # 将内容居中 对齐
        self.about_info.setAlignment(Qt.AlignCenter)  # 初始时隐藏关于页面

        # 创建一个布局用于关于页面，并将内容居中
        self.about_layout = QVBoxLayout()
        self.about_layout.addWidget(self.about_info)
        self.about_layout.addWidget(self.about_Version)
        self.about_layout.addWidget(self.about_author)
        self.about_layout.addWidget(self.about_Mail)
        self.about_layout.addStretch(1)  # 添加弹性空间，将内容推到中央

        # 创建关于页面的 QWidget，并设置布局
        self.about_widget = QWidget()
        self.about_widget.setLayout(self.about_layout)

        # 将所有页面添加到内容布局中
        self.content_layout.addWidget(self.home_widget)
        # self.content_layout.addWidget(self.help_label)
        self.content_layout.addWidget(self.about_widget)

        # 将内容小部件添加到主布局
        self.main_layout.addWidget(self.content_widget)

        self.setLayout(self.main_layout)

        # 默认显示主页
        self.show_home()

    def create_command_row(self, command):
        row_layout = QHBoxLayout()
        line_edit = NewLineEdit(command)
        button1 = QPushButton("发送1")

        line_edit.setMinimumSize(180, 25)  # 最小显示宽度
        button1.setFixedSize(40, 25)
        button1.clicked.connect(self.create_button_clicked_closure(line_edit))

        row_layout.setContentsMargins(0, 0, 0, 0)
        row_layout.setSpacing(3)
        row_layout.addWidget(line_edit)
        row_layout.addWidget(button1)

        return row_layout

    def create_button_clicked_closure(self, line_edit):
        """实现点击"""
        print("------------")
        def button_clicked():
            line_edit_text = line_edit.text()
            # self._update_command(line_edit_text)
            # self.right_list_layout.addLayout(self.create_command_row("asdfasdf"))

            self.right_list_layout.takeAt(self.right_list_layout.count()-1)
            self.right_list_layout.addLayout(self.create_command_row("asdf"))
            self.right_list_layout.addStretch(1)
            print("Asdfasdfasfd")

        return button_clicked

    def toggle_auto_send(self, state):
        """根据复选框状态启动或停止自动发送"""
        if state == Qt.Checked:
            print("Please send data")
            self.auto_send_timer.start(self.auto_send_interval)  # 开始自动发送
        else:
            self.auto_send_timer.stop()  # 停止自动发送

    def send_data(self):
        self.clear_send_buffer_button.setStyleSheet("background-color: red; color: white;")  # 默认红色
        self.clear_receive_buffer_button.setStyleSheet("background-color: red; color: white;")  # 默认红色
        self.send_button.setStyleSheet("background-color: green; color: white;")  # 默认红色
        try:
            # data = "1314521157"
            data = self.send_buffer.toPlainText()
            self.ser.write(data.encode())  # send data
            print(f"Sent data to {self.ser.port}")
            self.receive_data()  # 接收到的数据也添加到接收缓冲区中
        except Exception as e:
            # print(e)
            QMessageBox.information(self, "Warning", f"com ports: {self.ser.port} already Closed, Please Open ! ! ")
            print(f"Error sending data to {self.ser.port}")

    def receive_data(self):
        self.ser.timeout = 2  # timeout time in seconds
        try:
            while True:
                if self.ser.in_waiting > 0:
                    self.data = self.ser.read(self.ser.in_waiting).decode('utf-8')
                    print("receive data:", self.data)
                    self.receive_buffer.append(self.data)
                    break
                else:
                    print("no data, again to receive")
                    time.sleep(1)  # 若没有数据接收，则每1s检查一次

        except Exception as e:
            print(f"Error receiving data from {self.ser.port}")

    def update_com_ports(self):
        """更新COM端口列表"""
        ports = serial.tools.list_ports.comports()
        self.com_selector.clear()  # 清空当前列表
        for port in ports:
            self.com_selector.addItem(port.device)

    def show_home(self):
        self.home_widget.show()
        self.help_label.hide()
        self.about_widget.hide()
        self.update_menu(self.home_action)

    def show_help(self):
        self.home_widget.hide()
        self.help_label.show()
        self.about_widget.hide()
        # self.update_menu(self.help_action)

    def show_about(self):
        self.home_widget.hide()
        self.help_label.hide()
        self.about_widget.show()
        self.update_menu(self.about_action)

    def closeEvent(self, event):
        """捕捉关闭事件，弹出确认对话框"""
        reply = QMessageBox.question(self, '退出确认',
                                     "确定要退出吗？",
                                     QMessageBox.Yes | QMessageBox.No, QMessageBox.No)

        if reply == QMessageBox.Yes:
            event.accept()  # 如果用户选择 Yes，接受关闭事件，程序退出
        else:
            event.ignore()  # 如果用户选择 No，忽略关闭事件，程序继续运行

    def Version_box(self):
        """弹出版本信息对话框"""
        QMessageBox.about(self, '版本信息',
                          "Version: v1.0\n\n"
                          "无可升级版本\n")

    def update_menu(self, active_action):
        self.home_action.setChecked(False)
        # self.help_action.setChecked(False)
        self.about_action.setChecked(False)
        active_action.setChecked(True)

    def open_serial(self):
        """点击打开按钮时的操作"""
        # 修改按钮颜色
        self.open_button.setStyleSheet("background-color: green; color: white;")  # 变为绿色
        self.close_button.setStyleSheet("background-color: red; color: white;")  # 关闭按钮变为红色
        """打开串口"""
        # 获取串口参数
        self.com_port = self.com_selector.currentText()
        self.baudrate = int(self.baudrate_selector.currentText())
        self.data_bits = int(self.DataBit_selector.currentText())
        self.stop_bits = float(self.StopBit_selector.currentText())
        self.verify = self.VerifyBit_selector.currentText()
        self.hard_control = self.HardControl_selector.currentText()
        try:
            self.ser = serial.Serial(self.com_port, self.baudrate, timeout=1)
        except serial.SerialException as e:
            QMessageBox.information(self, "error", "Error opening serial port: " + str(e))
            print(f"Error opening serial port: {e}")
            return

    def close_serial(self):
        """点击关闭按钮时的操作"""
        # 修改按钮颜色
        self.open_button.setStyleSheet("background-color: red; color: white;")  # 恢复为红色
        self.close_button.setStyleSheet("background-color: green; color: white;")  # 恢复为绿色
        """关闭串口"""
        self.ser.close()
        pass

    def clear_SendBuffer(self):
        """清空发送缓冲区"""
        self.send_buffer.clear()
        self.clear_send_buffer_button.setStyleSheet("background-color: green; color: white;")  # 默认红色
        self.clear_receive_buffer_button.setStyleSheet("background-color: red; color: white;")  # 默认红色
        self.send_button.setStyleSheet("background-color: red; color: white;")  # 默认红色

    def clear_ReceiveBuffer(self):
        """清空接收缓冲区"""
        self.receive_buffer.clear()
        self.clear_send_buffer_button.setStyleSheet("background-color: red; color: white;")  # 默认红色
        self.clear_receive_buffer_button.setStyleSheet("background-color: green; color: white;")  # 默认红色
        self.send_button.setStyleSheet("background-color: red; color: white;")  # 默认红色

    def set_chinese_mode(self):
        """将页面内容设置为中文"""
        self.home_action.setText('主页')
        self.help_action.setTitle('帮助')
        self.about_action.setText('关于')
        self.chinese_mode_action.setText('中文模式')
        self.english_mode_action.setText('英文模式')
        self.upgrade_action.setText('版本升级')
        self.receive_buffer.setPlaceholderText("接收缓冲区")
        self.send_buffer.setPlaceholderText("发送缓冲区")
        self.auto_send_checkbox.setText('自动发送')
        self.serial_settings_groupbox.setTitle('串口设置')
        self.Switch_settings_groupbox.setTitle('串口开关')
        self.Com_Number.setText('端口号')
        self.Baud_label.setText('波特率')
        self.DataBit_label.setText('数据位')
        self.StopBit_Label.setText('停止位')
        self.VerifyBit_Label.setText('奇偶校验位')
        self.HardControl_Label.setText('硬件流控制')
        self.open_button.setText('打开')
        self.close_button.setText('关闭')
        self.about_info.setText('工具信息')
        self.VerifyBit_selector.clear()
        self.VerifyBit_selector.addItems(["无校验", "奇校验", "偶校验", "0校验", "1校验"])
        self.VerifyBit_selector.setCurrentText("无校验")  # 默认 无
        self.HardControl_selector.clear()
        self.HardControl_selector.addItems(["无", "有"])
        self.HardControl_selector.setCurrentText("无")
        self.send_button.setText("发送数据")
        self.clear_send_buffer_button.setText("清空发送缓冲区")
        self.clear_receive_buffer_button.setText("清空接收缓冲区")

    def set_english_mode(self):
        """将页面内容设置为英文"""
        self.home_action.setText('Home')
        self.help_action.setTitle('Help')
        self.about_action.setText('About')
        self.chinese_mode_action.setText('Chinese Mode')
        self.english_mode_action.setText('English Mode')
        self.upgrade_action.setText('Version Upgrade')
        self.receive_buffer.setPlaceholderText('Receive buffer text')
        self.send_buffer.setPlaceholderText('Send buffer text')
        self.auto_send_checkbox.setText('Auto Send')
        self.serial_settings_groupbox.setTitle('Serial Settings')
        self.Switch_settings_groupbox.setTitle('Serial Switch')
        self.Com_Number.setText('Com Number')
        self.Baud_label.setText('Baud Rate')
        self.DataBit_label.setText('Data Bit')
        self.StopBit_Label.setText('Stop Bit')
        self.VerifyBit_Label.setText('Verify Bit')
        self.HardControl_Label.setText('Hard Control')
        self.open_button.setText('Open')
        self.close_button.setText('Close')
        self.about_info.setText('Tool Information')
        self.VerifyBit_selector.clear()
        self.VerifyBit_selector.addItems(["No Verify", "Odd Verify", "Even Verify", "0 Verify", "1 Verify"])
        self.VerifyBit_selector.setCurrentText('No Verify')
        self.HardControl_selector.clear()
        self.HardControl_selector.addItems(["No", "Yes"])
        self.HardControl_selector.setCurrentText("No")
        self.send_button.setText("Send Data")
        self.clear_send_buffer_button.setText("Clear Send buffer")
        self.clear_receive_buffer_button.setText("Clear Receive buffer")


if __name__ == '__main__':
    app = QApplication(sys.argv)
    QApplication.setStyle(QStyleFactory.create('Fusion'))
    print(QStyleFactory.keys())
    window = Qserial_Assistant()
    window.show()
    sys.exit(app.exec_())
